#include "jcff_stc_tim.h"
static void TIM0_Config(TIM_InitTypeDef *TIM_Init);
static void TIM1_Config(TIM_InitTypeDef *TIM_Init);
static void TIM2_Config(TIM_InitTypeDef *TIM_Init);
static void TIM3_Config(TIM_InitTypeDef *TIM_Init);
static void TIM4_Config(TIM_InitTypeDef *TIM_Init);

/**
  * @brief  This function is to config timers
  * @note   
  * @param  TIM Timer to config, from timer0 to timer4
  *         TIM_Init Timer config parameter
  * @retval None
  */
RV TIM_Init(TIM_Type TIM, TIM_InitTypeDef *TIM_Init)
{
    switch(TIM)
    {
    case TIM0:
        TIM0_Config(TIM_Init);
        break;
    case TIM1:
        TIM1_Config(TIM_Init);
        break;
    case TIM2:
        TIM2_Config(TIM_Init);
        break;
    case TIM3:
        TIM3_Config(TIM_Init);
        break;
    case TIM4:
        TIM4_Config(TIM_Init);
        break;
    default:
        break;
    }
} 

/**
  * @brief  This function is to config timer0
  * @note   
  * @param  TIM_Init Timer config parameter
  * @retval None
  */
static void TIM0_Config(TIM_InitTypeDef *TIM_Init)
{
    /*Set the timer0 work mode*/
    switch (TIM_Init -> TIM_Mode)
    {
    case TIMER01234_16BIT_RELOAD: 
        TMOD = TMOD & 0xfc;
        break;
    case TIMER01_16BIT_ONCE:
        TMOD = TMOD & 0xfc | 0x01;
        break;
    case TIMER01_8BIT_RELOAD:
        TMOD = TMOD & 0xfc | 0x02;
        break;
    case TIMER0_16BIT_RELOAD_NMI:
        TMOD = TMOD & 0xfc | 0x03;
        break;
    default:
        break;
    }
    /*Select the clock source of timer 0*/
    switch (TIM_Init -> TIM_Source)
    {
    case INTERNAL_SOURCE:
        TMOD = TMOD & 0xfb;
        break;
    case EXTERNAL_SOURCE:
        TMOD = TMOD & 0xfb | 0x04;
        break;    
    default:
        break;
    }

    /*Set the timer 0 gate*/
    switch (TIM_Init -> EN_GATE)
    {
    case true:
        TMOD = TMOD & 0xf7;
        break;        
    case false:
        TMOD = TMOD & 0xf7 | 0x08;
        break;          
    default:
        break;
    }

    /*Set the timer 0 output*/
    switch (TIM_Init ->EN_CLK_OUTPUT)
    {
    case true:
        INTCLKO = INTCLKO & 0xfe | 0x01;
        break;
    case false:
        INTCLKO = INTCLKO & 0xfe;
        break;   
    default:
        break;
    }

    /*Set the timer 0 clock source prescaler*/
    switch (TIM_Init -> Prescaler)
    {
    case TIM_PRESCALER_1:
        AUXR = AUXR & 0x7f | 0x80;
        break;
    case TIM_PRESCALER_12:
        AUXR = AUXR & 0x7f;
        break;        
    default:
        break;
    }

    /*Set the counter register of timer 0*/
    TH0 = TIM_Init -> Period.TIMCount_Format8b[1]; 
    TL0 = TIM_Init -> Period.TIMCount_Format8b[0]; 
}

/**
  * @brief  This function is to config timer1
  * @note   
  * @param  TIM_Init Timer config parameter
  * @retval None
  */
static void TIM1_Config(TIM_InitTypeDef *TIM_Init)
{
    /*Set the timer1 work mode*/
    switch (TIM_Init -> TIM_Mode)
    {
    case TIMER01234_16BIT_RELOAD: 
        TMOD = TMOD & 0xcf;
        break;
    case TIMER01_16BIT_ONCE:
        TMOD = TMOD & 0xcf | 0x10;
        break;
    case TIMER01_8BIT_RELOAD:
        TMOD = TMOD & 0xcf | 0x20;
        break;
    default:
        break;
    }

    /*Select the clock source of timer 1*/
    switch (TIM_Init -> TIM_Source)
    {
    case INTERNAL_SOURCE:
        TMOD = TMOD & 0xbf;
        break;
    case EXTERNAL_SOURCE:
        TMOD = TMOD & 0xbf | 0x40;
        break;    
    default:
        break;
    }

    /*Set the timer 1 gate*/
    switch (TIM_Init -> EN_GATE)
    {
    case true:
        TMOD = TMOD & 0x7f;
        break;        
    case false:
        TMOD = TMOD & 0x7f | 0x80;
        break;          
    default:
        break;
    }

    /*Set the timer 1 output*/
    switch (TIM_Init ->EN_CLK_OUTPUT)
    {
    case true:
        INTCLKO = INTCLKO & 0xfd | 0x02;
        break;
    case false:
        INTCLKO = INTCLKO & 0xfd;
        break;   
    default:
        break;
    }

    /*Set the timer 1 clock source prescaler*/
    switch (TIM_Init -> Prescaler)
    {
    case TIM_PRESCALER_1:
        AUXR = AUXR & 0xbf | 0x40;
        break;
    case TIM_PRESCALER_12:
        AUXR = AUXR & 0xbf;
        break;        
    default:
        break;
    }
    /*Set the counter register of timer 1*/
    TH1 = TIM_Init -> Period.TIMCount_Format8b[1]; 
    TL1 = TIM_Init -> Period.TIMCount_Format8b[0]; 
}

/**
  * @brief  This function is to config timer2
  * @note   
  * @param  TIM_Init Timer config parameter
  * @retval None
  */
static void TIM2_Config(TIM_InitTypeDef *TIM_Init)
{
    /*Select the clock source of timer 2*/
    switch (TIM_Init -> TIM_Source)
    {
    case INTERNAL_SOURCE:
        AUXR = AUXR & 0xf7;
        break;
    case EXTERNAL_SOURCE:
        AUXR = AUXR & 0xf7 | 0x08;
        break;    
    default:
        break;
    }
    /*Set the timer 2 output*/
    switch (TIM_Init ->EN_CLK_OUTPUT)
    {
    case true:
        INTCLKO = INTCLKO & 0xfb | 0x04;
        break;
    case false:
        INTCLKO = INTCLKO & 0xfb;
        break;   
    default:
        break;
    }
    /*Set the timer 2 clock source prescaler*/
    switch (TIM_Init -> Prescaler)
    {
    case TIM_PRESCALER_1:
        AUXR = AUXR & 0xfb | 0x04;
        break;
    case TIM_PRESCALER_12:
        AUXR = AUXR & 0xfb;
        break;        
    default:
        break;
    }
    /*Set the counter register of timer 1*/
    T2H = TIM_Init -> Period.TIMCount_Format8b[1]; 
    T2L = TIM_Init -> Period.TIMCount_Format8b[0]; 
}

/**
  * @brief  This function is to config timer3
  * @note   
  * @param  TIM_Init Timer config parameter
  * @retval None
  */
static void TIM3_Config(TIM_InitTypeDef *TIM_Init)
{
    /*Select the clock source of timer 3*/
    switch (TIM_Init -> TIM_Source)
    {
    case INTERNAL_SOURCE:
        T4T3M = T4T3M & 0xfb;
        break;
    case EXTERNAL_SOURCE:
        T4T3M = T4T3M & 0xfb | 0x04;
        break;    
    default:
        break;
    }
    /*Set the timer 3 output*/
    switch (TIM_Init ->EN_CLK_OUTPUT)
    {
    case true:
        INTCLKO = INTCLKO & 0xfe | 0x01;
        break;
    case false:
        INTCLKO = INTCLKO & 0xfe;
        break;   
    default:
        break;
    }
    /*Set the timer 3 clock source prescaler*/
    switch (TIM_Init -> Prescaler)
    {
    case TIM_PRESCALER_1:
        AUXR = AUXR & 0xfd | 0x02;
        break;
    case TIM_PRESCALER_12:
        AUXR = AUXR & 0xfd;
        break;        
    default:
        break;
    }
    /*Set the counter register of timer 1*/
    T3H = TIM_Init -> Period.TIMCount_Format8b[1]; 
    T3L = TIM_Init -> Period.TIMCount_Format8b[0]; 
}

/**
  * @brief  This function is to config timer3
  * @note   
  * @param  TIM_Init Timer config parameter
  * @retval None
  */
static void TIM4_Config(TIM_InitTypeDef *TIM_Init)
{
    /*Select the clock source of timer 4*/
    switch (TIM_Init -> TIM_Source)
    {
    case INTERNAL_SOURCE:
        T4T3M = T4T3M & 0xbf;
        break;
    case EXTERNAL_SOURCE:
        T4T3M = T4T3M & 0xbf | 0x40;
        break;    
    default:
        break;
    }
    /*Set the timer 4 output*/
    switch (TIM_Init ->EN_CLK_OUTPUT)
    {
    case true:
        INTCLKO = INTCLKO & 0xef | 0x10;
        break;
    case false:
        INTCLKO = INTCLKO & 0xef;
        break;   
    default:
        break;
    }
    /*Set the timer 4 clock source prescaler*/
    switch (TIM_Init -> Prescaler)
    {
    case TIM_PRESCALER_1:
        AUXR = AUXR & 0xdf | 0x20;
        break;
    case TIM_PRESCALER_12:
        AUXR = AUXR & 0xdf;
        break;        
    default:
        break;
    }
    /*Set the counter register of timer 1*/
    T4H = TIM_Init -> Period.TIMCount_Format8b[1]; 
    T4L = TIM_Init -> Period.TIMCount_Format8b[0]; 
}

/**
  * @brief  Start or stop the timer 
  * @note   
  * @param  TIM Timer to control
  * @param  status : "true"-start the timer, "false"-stop the timer
  * @retval None
  */
void TIM_CountSwitch(TIM_Type TIM, BOOL status)
{
    switch (TIM)
    {
    case TIM0:
        if(status == true)
        {
            TR0 = 1;
        }
        else
        {
            TR0 = 0;
        }
        break;
    case TIM1:
        if(status == true)
        {
            TR1 = 1;
        }
        else
        {
            TR1 = 0;
        }
        break;

    case TIM2:
        if(status == true)
        {
            AUXR = AUXR & 0xf7 | 0x08;
        }
        else
        {
            AUXR = AUXR & 0xf7;
        }
        break;

    case TIM3:
        if(status == true)
        {
            T4T3M = T4T3M & 0xfb | 0x04;
        }
        else
        {
            T4T3M = T4T3M & 0xfb;
        }
        break;

    case TIM4:
        if(status == true)
        {
            T4T3M = T4T3M & 0xbf | 0x40;
        }
        else
        {
            T4T3M = T4T3M & 0xbf;
        }
        break;
       
    default:
        break;
    }
}

/**
  * @brief  Start or stop the timer 
  * @note   
  * @param  TIM Timer to control
  * @param  CntReg TIM_CounterRegisterType parameter it is a union type
  * @param  status : "true"-start the timer, "false"-stop the timer
  * @retval None
  */
void TIM_GetCurrentCount(TIM_Type TIM, TIM_CounterRegisterType *CntReg)
{
    switch (TIM)
    {
    case TIM0:
        CntReg ->TIMCount_Format8b[1] = TH0;
        CntReg ->TIMCount_Format8b[0] = TL0;
        break;
    case TIM1:
        CntReg ->TIMCount_Format8b[1] = TH1;
        CntReg ->TIMCount_Format8b[0] = TL1;
        break;
    case TIM2:
        CntReg ->TIMCount_Format8b[1] = T2H;
        CntReg ->TIMCount_Format8b[0] = T2L;
        break;
    case TIM3:
        CntReg ->TIMCount_Format8b[1] = T3H;
        CntReg ->TIMCount_Format8b[0] = T3L;
        break;
    case TIM4:
        CntReg ->TIMCount_Format8b[1] = T4H;
        CntReg ->TIMCount_Format8b[0] = T4L;
        break;
    }
}